#include "StdAfx.h"
#include "GameModule.h"
#include "LocalController.h"
#include "RemoteController.h"
#include "Actor.h"
#include "Weapon.h"
#include "Bullet.h"
#include "Hull.h"
#include "Shield.h"
#include "Engine.h"
#include "Function.h"
#include "WeaponFireManager.h"

#include "testWeapon.h"
#include "testBullet.h"


#include "PredefinedGameDataMessages.h"
#include "UMM_GameControllCommand.h"


//=>GAME

#include "GMM_AttachActorTo.h"
#include "GMM_DetachActorFrom.h"
//<=

//=>Collision
#include "CollisionMessages.h"
//<=

//=>Physics property
#include "PhysicsPropertyMessages.h"
//<=
        

namespace _MODULE_
{
	namespace _GAME_
	{
		
		GameModule::GameModule(void)
			:aEngineModule(_FOGGE_::eEMID_Game,__T("GameModule"))
		{
		//	m_ptrObjectMessageManager = foNEW ObjectMessageManager;
			
			
			
			//register message handller

			RegisterHandler(_PGDMSG::ePGDM_DataLoaded,&GameModule::OnDataLoaded);
			RegisterHandler(_PGDMSG::ePGDM_DataRemoved,&GameModule::OnDataRemoved);
			RegisterHandler(_PGDMSG::ePGDM_DataModified,&GameModule::OnDataModified);
			RegisterHandler(_UMMSG::eUMM_GameControllCommand,&GameModule::OnGameControllCommand);
			
		/**
		Collision Message handlers
		*/
		//@{
			RegisterHandler(_PMMSG::ePMM_CollisionCheckResult,&GameModule::OnCollisionCheckResult);
		//@}



			
			///register data part factory
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::ActorFactory);
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::HullFactory);
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::EngineFactory);
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::FunctionFactory);
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::GamePartFactory);
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::ShieldFactory);
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::WeaponFactory);
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::BulletFactory);

			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::testWeaponFactory);
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_GAME_::testBulletFactory);


			

			
			m_fAccumulatedGameCommandTime=0;
			
			
		}

		GameModule::~GameModule(void)
		{
		}

			/*virtual*/
		void GameModule::PostUpdate(float elapsedtime)
		{
			ProcessPostedMessage(GetMyID());
		}




		
		/*virtual*/
		bool GameModule::Initialize()
		{
			
			_DATAPART_::_GAME_::Actor* ptrActor;

			_DATAPART_::_GAME_::Actor* ptrPlayerActor;
			_DATAPART_::_GAME_::Actor* ptrRockActor;
			_DATAPART_::_GAME_::Actor* ptrRockActor2;

		//	_PMMSG::PMM_SetActorCollisionGroup *ptrSACG=
		//		FoDynamicCast(_PMMSG::PMM_SetActorCollisionGroup,GetNewMassage(_PMMSG::ePMM_SetActorCollisionGroup ));
		///	_PMMSG::PMM_SetActorCollisionGroup::ActorInfo info;

			

			
			ptrActor=FoDynamicCast(::_DATAPART_::_GAME_::Actor,i_GDBAccesser->LoadData(_T("PlayerShip.xml"),_FOGGE_::eEMID_Game));
			ptrActor->GetOwner()->ActivateDataObject();

			m_LocalControllerVector[0]->SetActor(ptrActor);
			//set actor physics group
		//	info.ptrDataObject=ptrActor->GetOwner();
		//	info.wGroupID=_DATAPART_::_GAME_::eGAT_Player;
		//	ptrSACG->m_ActorInfoVector.push_back(info);

			ptrPlayerActor=ptrActor;


			ptrActor=FoDynamicCast(::_DATAPART_::_GAME_::Actor,i_GDBAccesser->LoadData(_T("Rock.xml"),_FOGGE_::eEMID_Game));
			ptrActor->GetOwner()->ActivateDataObject();
			ptrActor->SetDesiredLocation(_FOMATH::Vector(200,0,0));
			//set actor physics group
/*			info.ptrDataObject=ptrActor->GetOwner();
			info.wGroupID=_DATAPART_::_GAME_::eGAT_Rock;
			ptrSACG->m_ActorInfoVector.push_back(info);

			ptrRockActor2=ptrActor;
*/
			ptrActor=FoDynamicCast(::_DATAPART_::_GAME_::Actor,i_GDBAccesser->LoadData(_T("Rock2.xml"),_FOGGE_::eEMID_Game));
			ptrActor->GetOwner()->ActivateDataObject();
			ptrActor->SetDesiredLocation(_FOMATH::Vector(0,200,0));
			//set actor physics group
/*			info.ptrDataObject=ptrActor->GetOwner();
			info.wGroupID=_DATAPART_::_GAME_::eGAT_Rock;
			ptrSACG->m_ActorInfoVector.push_back(info);

			


			ptrActor=FoDynamicCast(::_DATAPART_::_GAME_::Actor,i_GDBAccesser->LoadData(_T("Rock.xml"),_FOGGE_::eEMID_Game));
			ptrActor->GetOwner()->SetLocation(_FOGGE_::eEMID_Game,0,0,-200);
			//set actor physics group
			info.ptrDataObject=ptrActor->GetOwner();
			info.wGroupID=_DATAPART_::_GAME_::eGAT_Rock;
			ptrSACG->m_ActorInfoVector.push_back(info);

			ptrRockActor=ptrActor;



			//send set group msg
			ptrSACG->PushReceiver(_FOGGE_::eEMID_Physics);
			SendMessage(ptrSACG);
			

			//send collision check message
			_PMMSG::PMM_SetCollisionCheck *ptrTCC=FoDynamicCast(_PMMSG::PMM_SetCollisionCheck,GetNewMassage(_PMMSG::ePMM_SetCollisionCheck ));
			ptrTCC->m_wGroupID1=_DATAPART_::_GAME_::eGAT_Player;
			ptrTCC->m_wGroupID2=_DATAPART_::_GAME_::eGAT_Rock;
			ptrTCC->m_bCollision=true;
			ptrTCC->PushReceiver(_FOGGE_::eEMID_Physics);
			SendMessage(ptrTCC);

			


			//Subscribe for a collisionReport
			_PMMSG::PMM_SubscribeForCollisionReport *ptrSCR=FoDynamicCast(_PMMSG::PMM_SubscribeForCollisionReport,GetNewMassage(_PMMSG::ePMM_SubscribeForCollisionReport));
			ptrSCR->m_wGroupID1=_DATAPART_::_GAME_::eGAT_Player;
			ptrSCR->m_wGroupID2=_DATAPART_::_GAME_::eGAT_Rock;

			ptrSCR->m_bWhenOnTouch=false;
			ptrSCR->m_bWhenStartTouch=true;
			ptrSCR->m_bWhenEndTouch=false;
			ptrSCR->PushReceiver(_FOGGE_::eEMID_Physics);
			SendMessage(ptrSCR);


			// send attatchment info
			_GMMSG::GMM_AttachActorTo* ptrAA=
				FoDynamicCast(_GMMSG::GMM_AttachActorTo,GetNewMassage(_GMMSG::eGMM_AttachActorTo));

					
			ptrAA->m_ptrDataAttachBase=ptrPlayerActor->GetOwner();
			ptrAA->m_ptrDataToAttach=ptrRockActor->GetOwner();

			BroadcastMessage(ptrAA);
*/
		/*	ptrAA=
				FoDynamicCast(_GMMSG::GMM_AttachActorTo,GetNewMassage(_GMMSG::eGMM_AttachActorTo));


			ptrAA->m_ptrDataAttachBase=ptrRockActor->GetOwner();
			ptrAA->m_ptrDataToAttach=ptrRockActor2->GetOwner();

			BroadcastMessage(ptrAA);
		*/
			m_bIsInitialized = true;


			return true;
		}

		/*virtual*/
		bool GameModule::SystemInitialize()
		{
			//for singleplayer controller
			m_LocalControllerVector.push_back(foNEW LocalController);

			_P_GAME::Weapon::g_ptrWeaponFireManager=foNEW WeaponFireManager;

			return true;
		}
		/*virtual*/
		void GameModule::SystemFinalize()
		{
			for(int i=0;i<m_LocalControllerVector.size();i++)
			{
				foDELETE(m_LocalControllerVector[i]);
			}
			m_LocalControllerVector.clear();


			for(int i=0;i<m_RemoteControllerVector.size();i++)
			{
				foDELETE(m_RemoteControllerVector[i]);
			}
			m_RemoteControllerVector.clear();

			foDELETE(_P_GAME::Weapon::g_ptrWeaponFireManager);

		}
			
		/*virtual*/
		void GameModule::Update(float elapsedtime)
		{

			UpdateGameCommands(elapsedtime);

			UpdateGameParts(elapsedtime);
		
		}
		////////////////////////////

		void GameModule::UpdateGameParts(float elapsedtime)
		{
			std::set<_P_GAME::GamePart*>::iterator iter,end;
			iter=m_setGamePart.begin();
			end=m_setGamePart.end();

			for(;iter!=end;++iter)
			{
				_P_GAME::GamePart* ptrPart=*iter;

				ptrPart->Update(elapsedtime);

			}

		}
		///////////////////////////

		void GameModule::UpdateGameCommands(float elapsedtime)
		{
			
			m_fAccumulatedGameCommandTime+=elapsedtime;

			if(m_fAccumulatedGameCommandTime<0.1f)
				return;
			m_fAccumulatedGameCommandTime=0;

			for(int i=0;i<m_LocalControllerVector.size();i++)
			{
				m_LocalControllerVector[i]->Update(elapsedtime);
			}


	/*		for(int i=0;i<m_RemoteControllerVector.size();i++)
			{
				m_RemoteControllerVector[i]->Up);
			}
			m_RemoteControllerVector.clear();
*/
		}


		/////////////////////
		HRESULT GameModule::OnDataLoaded(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PGDMSG::PGDM_DataLoaded *ptrDL=FoDynamicCast(_PGDMSG::PGDM_DataLoaded,ptrMsg);


			_P_GAME::GamePart* ptrGamePart=FoDynamicCast(_P_GAME::GamePart,ptrDL->m_ptrDataObject->GetDataPart(_FOGGE_::eEMID_Game));

			ptrGamePart->GetOwner()->IncRefCount();

			m_setGamePart.insert(ptrGamePart);
			
			return S_OK;

		}

		HRESULT GameModule::OnDataRemoved(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PGDMSG::PGDM_DataRemoved *ptrDR=FoDynamicCast(_PGDMSG::PGDM_DataRemoved,ptrMsg);


			_P_GAME::GamePart* ptrGamePart=FoDynamicCast(_P_GAME::GamePart,ptrDR->m_ptrDataObject->GetDataPart(_FOGGE_::eEMID_Game));
			m_setGamePart.erase(ptrGamePart);
			
			
			return S_OK;
		}
		///////////////////////////////////////////////////////////////

		HRESULT GameModule::OnDataModified(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			
			return S_OK;

		}
		
		
		HRESULT GameModule::OnGameControllCommand(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{

			_UMMSG::UMM_GameControllCommand *ptrGCC=FoDynamicCast(_UMMSG::UMM_GameControllCommand,ptrMsg);



			if(m_LocalControllerVector[ptrGCC->m_iLocalUserID]->ProcessCommand(ptrGCC->m_GameCommand ,ptrGCC->m_CommandFlag)==false)
			{//not processed
				if(ptrGCC->m_GameCommand==_T("MouseMoving"))
				{
				}
				else if(ptrGCC->m_GameCommand==_T("ToggleCameraRotateYawPitch"))
				{
				}
				else if(ptrGCC->m_GameCommand==_T("ToggleCameraRotateRoll"))
				{
				}

			}

			return S_OK;

		}

		/////////////////////////////////////////////
		HRESULT GameModule::OnCollisionCheckResult(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			return S_OK;
		}
	}
}